package com.akk.module.authentication;

import com.akk.exception.RestBusinessException;
import com.akk.module.authentication.model.request.AuthRequest;
import com.akk.module.authentication.model.response.AuthResponse;
import com.akk.module.authentication.utils.Cipher3DES;
import com.akk.module.authentication.utils.HttpRequestClient;
import com.akk.module.authentication.utils.RsaSignCoder;
import com.akk.utils.Constants;
import com.akk.utils.DateUtils;
import net.sf.json.JSONObject;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;

public abstract class AuthService {
    private Logger logger = LoggerFactory.getLogger(AuthService.class);

    public abstract AuthResponse auth(AuthRequest request);

    JSONObject getAuthMessage(String userCode, String appCode, String qryReason, JSONObject content){
        /** 生成请求报文**/
        JSONObject headerJson = new JSONObject();
        headerJson.put("qryBatchNo", DateUtils.formatDateTimeNoInterval(new Date()) + (int) (Math.random() * 10000));//验证批次号  用户生成的唯一编号
        headerJson.put("userCode", userCode);//商户编号，即用户编号
        headerJson.put("sysCode",appCode);//应用编号
        headerJson.put("qryReason", qryReason);//原因
        headerJson.put("qryDate", DateUtils.formatDateNoInterval(new Date()));//格式：yyyyMMdd
        headerJson.put("qryTime", DateUtils.formatTimeNoInterval(new Date()));//格式：hhmmss
        JSONObject allJson = new JSONObject();
        allJson.put("header", headerJson);
        allJson.put("condition", content);
        return allJson;
    }

    JSONObject sendEncMessage(String message , String url, String appKey, String vector, String userCode, String privateKey) {
        //加密请求报文
        String encData;
        String signature;
        try {
            encData = Cipher3DES.encrypt(message,appKey ,vector );
            signature = RsaSignCoder.sign(encData, privateKey );
        } catch (Exception e) {
            throw new RestBusinessException("实名认证异常.");
        }
        //请求API对应的接口
        List<NameValuePair> parameters = new ArrayList<>();
        parameters.add(new BasicNameValuePair("condition", encData));
        parameters.add(new BasicNameValuePair("userCode", userCode));
        parameters.add(new BasicNameValuePair("signature", signature));
        parameters.add(new BasicNameValuePair("vector", vector));
        String result;
        try {
            result = HttpRequestClient.invoke_http(url, parameters, "UTF-8");
        } catch (Exception e) {
            throw new RestBusinessException("实名认证服务器异常");
        }
        //获取接口返回报文
        Map<String, String> resultMap = new HashMap<>();
        //将json字符串转换成jsonObject
        JSONObject requestJson = JSONObject.fromObject(result);
        Iterator<String> it = requestJson.keys();

        //遍历jsonObject数据，添加到Map对象
        while (it.hasNext()) {
            String key = String.valueOf(it.next());
            String value = String.valueOf(requestJson.get(key));
            resultMap.put(key, value);
        }
        String sign = resultMap.get("signature");
        String datas = resultMap.get("contents");

        /** 验签及解密报文**/
        //验证加密内容报文的签名
        boolean contents = false;
        try {
            contents = RsaSignCoder.verify(datas, Constants.AUTH_SIGN_PUBLIC_KEY, sign);
        } catch (Exception e) {
            logger.error("实名认证出错.-->状态码:"+resultMap.get("code")+"/详情:"+resultMap.get("codeDesc"));
            throw new RestBusinessException("服务器繁忙.");
        }
        //先判断contents，如果contents 不为空，那就解密，判断里面是否存在msg 或者data，如果contents是空的，就直接取明文msg
        //确认解签是否通过  返回true则表示验证通过 下一步进行解密报文体加密数据（签名主要用于验证报文数据是否被篡改）
        if (!contents)
            throw new RestBusinessException("验签失败，请检查秘钥是否正确");
        //验签通过则进行解密返回的加密报文
        String str;
        try {
            str = Cipher3DES.decrypt(datas, appKey, vector);
        } catch (Exception e) {
            throw new RestBusinessException("解析报文异常");
        }
        JSONObject jsonObject = JSONObject.fromObject(str);
        return jsonObject;

    }

}
